home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
yerk
/
mps231ss.hqx
/
Mops source
/
Toolbox classes
/
PrintManager
< prev
next >
Wrap
Text File
|
1992-07-25
|
7KB
|
254 lines
\ 24Jul92 DBH
\ note that dlen from the source file class was redefined as a value in
\ the source file struct
: DataLength ( ^class -- n ) \ given a pointer to a class, return the
\ length of the ivar data
dlen&xwid drop ;
\ define the non-trivial toolbox calls as normal words, not required, but
\ this makes it easier to follow the methods, I think
: PrValidate { thPrint -- b }
word0 thPrint call PrValidate i->l ;
: PrStlDialog { thPrint -- b }
word0 thPrint call PrStlDialog i->l ;
: PrJobDialog { thPrint -- b }
word0 thPrint call PrJobDialog i->l ;
: PrOpenDoc { thPrint tpPrPort tpIOBuf -- TPPrPort }
0 thPrint tpPrPort tpIOBuf call PrOpenDoc ;
: PrError ( -- errorCode )
word0 call PrError i->l ;
\ now define some classes for the purpose of mapping into the Mac records
:class TPrInfo super{ object }
int iDev
int iVRes \ vertical resolution of printer
int iHRes \ horizontal resolution of printer
rect rPage \ page rectangle
;class
:class TPrStl super{ object }
int wDev \ high byte specifies device (1=ImageWriter, 3=LaserWriter)
6 bytes junk \ more fields for internal use, not mapped
;class
:class TPrJob super{ object }
int iFstPage
int iLstPage
int iCopies
byte bJDocLoop \ print method, 0=draft 1=spooled
bool fFromUsr
ptr pIdleProc \ background procedure
ptr pFileName
4 bytes junk
:m spooled?: ( -- b)
get: bJDocLoop 1 = ;m
;class
:class THPrint super{ object }
int iPrVersion
TPrInfo prInfo
rect rPaper
TPrStl prStl
TPrInfo prInfoPT
16 bytes prXInfo \ not mapped due to very limited use
TPrJob prJob
38 bytes printX
:m spooled?: ( -- b)
spooled?: prJob ;m
;class
:class TPrStatus super{ object }
int iTotPages \ number of pages in spool file
int iCurPage \ page being printed
int iTotCopies \ number of copies requested
int iCurCopy \ copy being printed
int iTotBands \ used internally
int iCurBand \ used internally
bool fPgDirty \ true if started printing page
bool fImaging \ used internally
handle hPrint \ print record
var pPrPort \ printing grafport
handle hPic \ used internally
;class
:class PrintManager super{ object }
handle hPrint
TPrStatus prStatus
x-addr draw \ draw handler for printing
:m put: ( cfa -- )
put: draw ;m
:m new: \ must call new: only once at runtime to allocate print record
['] THPrint DataLength new: hPrint ;m
:m getnew: \ this method should obtain a print record from the resource
\ fork of the file, if a file exists that is ( see PageSetup: comments
\ and see IM II-150 Note: )
\ This method is not implemented here, but would be used in place of new:.
;m
:m release:
release: hPrint ;m
:m PageSetup: ( -- b) \ rundialog, returns 0 if user cancel
\ if user did not cancel, it might be a good idea to save the hprint record
\ to disk so the printing parameters chosen by the user can be restored.
\ But this restoration is not automatic and must be done by the program.
call PrOpen
PrError 0=
IF
get: hPrint PrStlDialog
THEN
call PrClose ;m
private
\ note, only printing one page here ( so this isn't really a loop)
:m printLoop: { \ pPrPort -- }
get: hPrint 0 0 PrOpenDoc -> pPrPort
PrError 0=
IF
pPrPort 0 call PrOpenPage \ pPageFrame=0, so no scaling
PrError 0=
IF
exec: draw
THEN
pPrPort call PrClosePage
THEN
pPrPort call PrCloseDoc
PrError 0=
ptr: hPrint spooled?: THPrint and \ note message to class THPrint
IF
get: hPrint 0 0 0 addr: prStatus call PrPicFile
THEN
;m
public
:m Print:
call PrOpen
PrError 0=
IF
pushport
get: hPrint PrJobDialog
IF printLoop: self THEN
popport
THEN
call PrClose ;m
;class
PrintManager pm \ instantiate an object, named pm, to do all printing work
endload
********* Example usage of Print Manager **********
: testPrint
30 30 80 80 put: temprect
draw: temprect ;
' testPrint put: pm \ put the draw action in our PrintManager object
new: pm \ must always call new: only once at runtime
PageSetup: pm . \ not required, but does what it says
Print: pm \ let er rip
release: pm \ not required till quitting, i.e. can do multiple Print:'s
\ without calling this. This just releases some memory.
****** Possible Enhancements ********
Of course, we need to cycle through and print each requested page.
I think a better printing model could be achieved by having a " print object"
instance variable in the PrintManager class. It would simply be sent a
print: message at the correct time, rather than sending exec: to an x-addr
as is done here. I think it would be more flexible and robust to have the
PrintManager object communicate with a print object.
It would probably make sense to have printing be a function of the
page rectangle and page number. So the print object would always
be passed this information when a page is requested to be drawn.
And probably the message should be PrintPage: with the rectangle and
page number passed as parameters to the print object.
Also, a way to easily save and restore the the page setup parameters in a
file's resource fork would be nice. See suggested message getnew:.
SInce no background procedure is provided, the toolbox will default to
cancelling upon command-period. See IM II-152,153. But it shouldn't be
difficult to provide a custom background procedure.
****** Comments *******
Note the use of a class definition to map into a toolbox-created record,
in this case the THPrint record. In the printLoop: method of class PrintManager
we need to access a member of a record that is contained in a subrecord, in
this case bjDocLoop (member of TPrJob, which is a subrecord of THPrint).
Now we could have simply obtained the pointer to the print record, added
the correct offset, and performed a c@:
ptr: hPrint offset + c@
But there are some problems with this approach, even though it may seem more
straightforward. First, one must compute the offset. I have no idea what it
is, nor do I wish to know. Second, one must remember to perform the correct
type of "fetch" (c@ here, or was it c@x?). Thirdly, I don't think it is very
clear what is going on here.
Instead, I believe a better approach is to define the records as classes,
define the required access methods, and then pass a message to a class with
the appropriate base address on the stack:
ptr: hPrint spooled?: THPrint
Here the spooled?: message will be passed by class THPrint to its prJob ivar
which will obtain the value of bjDocLoop contained in the record pointed to
by ptr: hPrint.
One must be careful when passing a message to a class that the address
on the stack really does point to a data structure that matches the class.
The offset (to bjDocLoop) is automatically computed, the appropriate "fetch"
is automatically performed, and it is very clear what is going on. Also,
one does not need to know the length of the THPrint record when allocating
memory for the handle hPrint. Merely passing the class pointer to DataLength
will do that job ( see definition of DataLength at the beginning of this file)
as in the new: method for PrintManager.
Doug Hoffman 24Jul92
Compuserve 72310,1743